package vista.treeDiagrama;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Iterator;

import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import vista.objetos.DiagramaGraficable;
import vista.objetos.GraficableConEtiqueta;
import vista.objetos.NoEsObjetoNodoException;

@SuppressWarnings("serial")
public class TreeDeDiagrama extends JTree implements MouseListener {
	
	private DefaultTreeModel modeloArbol;
	private DefaultMutableTreeNode raiz;
	private DefaultMutableTreeNode diagramaActual;
	
	public TreeDeDiagrama(DiagramaGraficable diagrama, JFrame contenedor)
	{
		super(new DefaultTreeModel(new DefaultMutableTreeNode(new NodoDiagrama(diagrama))));
		
        inicializar();
        diagrama.setNodo(this.raiz);
        
		this.diagramaActual = this.raiz;
		
		DefaultMutableTreeNode carpetaObjetos= new DefaultMutableTreeNode(new NodoObjeto());
		this.modeloArbol.insertNodeInto(carpetaObjetos, this.raiz, this.raiz.getChildCount());
	    
	    cargarGraficablesAlArbol(diagrama, contenedor);
	    
	    this.cargarDiagramas(diagrama, diagramaActual, contenedor);
	    this.diagramaActual = this.raiz;
	    //  esto no sirve para nada, ver si lo puedo arreglar -> esto va a seguir sin servir para nada :P
		TreePath parentPath = this.getSelectionPath();
	    this.expandPath(parentPath);
	}

	private void cargarGraficablesAlArbol(DiagramaGraficable diagrama, JFrame contenedor)
	{
		Iterator<GraficableConEtiqueta> itGraficable = diagrama.getGraficables().iterator();
	    
	    while (itGraficable.hasNext())
	    {
	    	GraficableConEtiqueta graficable = itGraficable.next(); 
	    	try
	    	{
		    	NodoTreeDiagrama nodo = graficable.getNodoTreeDiagrama();
		    	this.agregarNodoTree(nodo);
		    	graficable.setNodo(nodo);
		    	nodo.getPopupMenu().escucharEventoEditar(graficable.getEventoEditarGraficable(contenedor));
	    	}
	    	catch (NoEsObjetoNodoException e) {	}
	    }
	}

	private void inicializar()
	{
		this.setCellRenderer(new TreeRenderParaDiagrama());
		this.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		this.addMouseListener(this);
		
		this.modeloArbol = (DefaultTreeModel) this.getModel();
		this.raiz = (DefaultMutableTreeNode) this.modeloArbol.getRoot();
	}
	
	public void agregaDiagrama(DiagramaGraficable diagrama, JFrame contenedor)
	{
		this.agregarDiagramaAlArbol(diagrama, this.diagramaActual);
		this.cargarGraficablesAlArbol(diagrama, contenedor);
	}
	
	private void cargarDiagramas(DiagramaGraficable diagramaPadre, DefaultMutableTreeNode diagramaActual, JFrame contenedor)
	{
	    for(DiagramaGraficable diagramaHijo: diagramaPadre.getDiagramasHijos())
	    {
			this.agregarDiagramaAlArbol(diagramaHijo, diagramaActual);
			this.cargarGraficablesAlArbol(diagramaHijo, contenedor);
			this.cargarDiagramas(diagramaHijo, this.diagramaActual, contenedor); 
	    }
	}
	
	public void cambiarDiagramaActual(DiagramaGraficable diagActual) {
		this.diagramaActual = diagActual.getNodo();
	}
	
	private void agregarDiagramaAlArbol(DiagramaGraficable diagrama, DefaultMutableTreeNode nodoPadre )
	{
		NodoDiagrama nodo = new NodoDiagrama(diagrama);
		
		DefaultMutableTreeNode nodoHijo = new DefaultMutableTreeNode(nodo);
		DefaultMutableTreeNode carpetaObjetos= new DefaultMutableTreeNode(new NodoObjeto());
        
        this.modeloArbol.insertNodeInto(nodoHijo, nodoPadre, nodoPadre.getChildCount());
        this.modeloArbol.insertNodeInto(carpetaObjetos, nodoHijo, nodoHijo.getChildCount());
        
        this.expandPath(new TreePath(nodoHijo));
        
//        Iterator<Diagrama> iterador = diagrama.getDiagramasHijo().iterator();
//	    
//        while (iterador.hasNext())
//        	this.agregarDiagramaAlArbol(iterador.next(), nodoHijo);
        this.diagramaActual = nodoHijo;
        diagrama.setNodo(nodoHijo);
	}    
	
	public void agregarNodoTree(NodoTreeDiagrama nodoTreeDiagrama)
	{
		DefaultMutableTreeNode nodoPadre = (DefaultMutableTreeNode) diagramaActual.getChildAt(0);
		DefaultMutableTreeNode nodoHijo = new DefaultMutableTreeNode(nodoTreeDiagrama);

		nodoTreeDiagrama.setMutTreeNode(nodoHijo);
		nodoTreeDiagrama.setArbol(this);
		
		int i = getNroPosOrdenAlfabetico(nodoPadre, nodoHijo);
        this.modeloArbol.insertNodeInto(nodoHijo, nodoPadre, i); 
 	}

	private int getNroPosOrdenAlfabetico(DefaultMutableTreeNode nodoPadre, DefaultMutableTreeNode nodoHijo) 
	{
		int i = 0;
		
		for (; i < nodoPadre.getChildCount(); i++)
		{
			if (nodoPadre.getChildAt(i).toString().compareToIgnoreCase(nodoHijo.toString()) > 0)
				break;
		}
		return i;
	}  
	
	public void quitarNodoTree(MutableTreeNode nodoTreeDiagrama)
	{	
		MutableTreeNode parent = (MutableTreeNode)(nodoTreeDiagrama.getParent());

		if (parent != null)
			this.modeloArbol.removeNodeFromParent(nodoTreeDiagrama);
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		checkPopup(e);
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		checkPopup(e);	
	}

	@Override
	public void mouseExited(MouseEvent e) {
		checkPopup(e);	
	}

	@Override
	public void mousePressed(MouseEvent e) {
		checkPopup(e);	
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		checkPopup(e);
	}

	private void checkPopup(MouseEvent e) 
	{	
	
		TreePath pathAlNodo = this.getSelectionPath();
	    TreePath tp = this.getPathForLocation(e.getX(), e.getY());

		if (pathAlNodo == null || tp == null)
			return;
		
	    
	    if (pathAlNodo != tp)
	    	return;
		
		if (e.isPopupTrigger())
		{
			DefaultMutableTreeNode nodo = (DefaultMutableTreeNode)pathAlNodo.getLastPathComponent();
			NodoTreeDiagrama objeto = (NodoTreeDiagrama) nodo.getUserObject();
			objeto.mostrarPopupMenu(this, e.getX(), e.getY());
		}
		
	}	
//	public List<Atributo> getAtributos()
//	{
//		List<Atributo> objetos = new LinkedList<Atributo>();
//		
//		int nroElemento = 0;
//		while (nroElemento < this.modeloArbol.getChildCount(raiz))
//		{
//			DefaultMutableTreeNode nodo = (DefaultMutableTreeNode)this.modeloArbol.getChild(raiz, nroElemento); 
//			objetos.add((Atributo)nodo.getUserObject());
//			nroElemento++;
//		}
//		
//		return objetos;
//	}
		

}
